#include <iostream>
#include <stack>

using namespace std;

template<class vertexType>
class Graph
{
public:
    Graph(int vnum) //конструктор - создает матрицу смежности нужного размера и вспомогательные массивы
    {
        vertexNum = vnum;
        adjList = new int*[vnum];
        for(int i = 0; i < vnum; i++)
        {
            adjList[i] = new int[vnum];
            for(int j = 0; j < vnum; j++)
                adjList[i][j] = 0;
        }
        tin = new int[vertexNum];
        f = new int[vertexNum];
        color = new int[vertexNum];
        for (int i = 0; i < vertexNum; i++)
        {
            tin[i] = 0;
            f[i] = -1;
            color[i] = 0;
        }
    }
    ~Graph() //деструктор, освобождающий память
    {
        for (int i = 0; i < vertexNum; i++)
        {
            delete adjList[i];
        }
        delete[] adjList;
        delete tin;
        delete f;
        delete color;
    }
    
    bool addEdge(int edge1, int edge2) //добавление ребра между вершинами
    {
        if (edge1 > vertexNum || edge2 > vertexNum)
            return false;
        adjList[edge1 - 1][edge2 - 1] = 1;
        return true;
    }
    
    void DFS(int root) // Поиск в глубину + Тарьян
    {
        if (tin[root] == 0) //входим в цикл если время входа в вершину 0(т.е. мы еще не посещали ее)
        {
            DFSstack.push(root); //добавляем вершину в стек
            f[root] = tin[root] = ++times; //задаем стандартные значения для времени входа и функции
            for (int i = 0; i < vertexNum; i++) //теперь ищем смежную вершину которая не входит в
            {                                                     //никакие КСС(для нее значение цвета 0)
                if (adjList[root][i] == 1)
                {
                    if (color[i] == 0)
                    {
                        if (tin[i] == 0)    //если мы нашли подходяшую вершину то запускаем дфс из нее
                            DFS(i);
                        f[root] = min(f[root], f[i]); //после того как мы вернулись из смежной вершины
                    }                                 //вычисляем функцию
                }
            }

            if (f[root] == tin[root]) //если значение функции после обхода всех смежных вершин осталось
            {                         //прежним, то эта вершина - точка входа в КСС
                int u;
                CSSnum++; //общее число КСС
                do { //удаляем из стека все вершины вплоть до точки входа в КСС и перекрашиваем их в
                    u = DFSstack.top(); //массиве color в одинаковый цвет
                    color[u] = CSSnum;
                    DFSstack.pop();
                } while (u != root);
            }
        }
    }
    
    void SCC() //поиск и вывод всех КСС
    {
        DFS(0); //из нулевой вершины запускаем алгоритм Тарьяна
        for (int i = 0; i < vertexNum; i++) //если остались неокрашенные вершины запускаем Тарьяна из них
            if (color[i] == 0)
                DFS(i);
        
        for (int i = 0; i < CSSnum; i++) //в результате в массиве color все вершины будут иметь цвет своей КСС
        {
            cout << i + 1 << ": ";
            for (int j = 0; j < vertexNum; j++)
            {
                if (color[j] == i + 1)
                    cout << j + 1 << " ";
            }
            cout << "\n";
        }

        for (int i = 0; i < vertexNum; i++) //возвращаем значения вспомогательных массивов на стандартные
        {
            tin[i] = 0;
            f[i] = -1;
            color[i] = 0;
        }
        CSSnum = times = 0;
    }
    
private:
    int vertexNum = 0;
    int edgeNum;
    int** adjList;
    int* tin;
    int* color;
    int CSSnum = 0;
    int* f;
    int times = 0;
    stack<int> DFSstack;
};

int main()
{
    int n, m;
    cin >> n >> m; //считываем общее число вершин и число ребер
    Graph<int> g1(n); //создаем граф
    int e1, e2;
    for (int i = 0; i < m; i++) //считываем ребра
    {
        cin >> e1 >> e2;
        g1.addEdge(e1,e2);
    }
    g1.SCC(); //запускаем алгоритм поиска всех КСС
    return 0;
}